package com.jmp.security.grant.userApi;

import com.jmp.base.PlatformApi;
import com.jmp.base.dto.AccountResponse;
import com.jmp.security.base.ClientDetail;
import com.jmp.security.base.UserDetail;
import com.jmp.security.base.UserDetailService;
import com.jmp.security.grant.wx.WxCodeRequestDetail;
import com.jmp.security.grant.wx.WxLoginService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import one.stand.dto.WechatLoginDto;
import one.stand.dto.WechatUserInfoDto;
import one.stand.mapper.CompanyPlatformMapperServiceLoginExt;
import one.stand.model.CompanyPlatform;
import one.stand.model.User;
import one.stand.service.UserService;
import one.stand.service.user.UserAdminService;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;

@Slf4j
public class UserApiWxUserDetailServiceImpl implements UserDetailService<WxCodeRequestDetail> {
    private UserAdminService userAdminService;
    private WxLoginService wxLoginService;
    private CompanyPlatformMapperServiceLoginExt companyPlatformMapperServiceLoginExt;
    private UserService userService;

    public UserApiWxUserDetailServiceImpl(UserAdminService userAdminService, WxLoginService wxLoginService, CompanyPlatformMapperServiceLoginExt companyPlatformMapperServiceLoginExt, UserService userService) {
        this.userAdminService = userAdminService;
        this.wxLoginService = wxLoginService;
        this.companyPlatformMapperServiceLoginExt = companyPlatformMapperServiceLoginExt;
        this.userService = userService;
    }

    @Override
    public UserDetail get(WxCodeRequestDetail requestDetail, ClientDetail clientDetail) {
        final boolean isOneUserLogin = isOneUserLogin(requestDetail.getCompanyKey());

        WxUserDetail userDetail = new WxUserDetail();
        codeOauth(requestDetail, clientDetail, userDetail, isOneUserLogin);

        if (Objects.isNull(userDetail.getUserModel())) {
            saveUser(clientDetail.getCompanyAccountModel().getCompanyId(), userDetail);
        } else {
            updateUser(requestDetail, userDetail, isOneUserLogin);
        }

        userService.saveUserLoginWx(userDetail.getUserModel().getUserId(), requestDetail.getLoginEnum().getAccountType(),
                requestDetail.getCompanyKey(), userDetail.getWechatLoginDto().getOpenId());

        User inModel = userAdminService.getByUserId(userDetail.getUserModel().getUserId());//重新获取最新User信息
        userDetail.setUserModel(inModel);
        userDetail.setSessionKey(userDetail.getWechatLoginDto().getSessionKey());
        return userDetail;
    }

    private void updateUser(WxCodeRequestDetail request, WxUserDetail userDetail, boolean isOneUserLogin) {
        User inModel = userDetail.getUserModel();
        WechatLoginDto wechatLoginDto = userDetail.getWechatLoginDto();
        WechatUserInfoDto userInfoDto = userDetail.getUserInfoDto();

        User userModel = new User();
        if (StringUtils.isBlank(inModel.getUnionid())
                && StringUtils.isNoneBlank(wechatLoginDto.getUnionId())) {
            userModel.setUserId(inModel.getUserId());
            userModel.setUnionid(wechatLoginDto.getUnionId());
        }
        if (isOneUserLogin) {
            userModel.setUserId(inModel.getUserId());
            userModel.setThirdCompanyKey(request.getCompanyKey());
        }
        final boolean isUpdateUserInfo = userAdminService.isVisit(inModel.getAvatarUrl()) && Objects.nonNull(userInfoDto);
        if (isUpdateUserInfo) {
            userModel.setUserId(inModel.getUserId());
            userModel.setNickeName(userInfoDto.getNickName());
            userModel.setAvatarUrl(userInfoDto.getAvatarUrl());
            userModel.setGender(userInfoDto.getGender());
            userModel.setCity(userInfoDto.getCity());
            userModel.setProvince(userInfoDto.getProvince());
            userModel.setCountry(userInfoDto.getCountry());
        }
        if (StringUtils.isBlank(inModel.getOpenId())) {
            userModel.setUserId(inModel.getUserId());
            userModel.setOpenId(wechatLoginDto.getOpenId());

            userService.deleteByOpenId(wechatLoginDto.getOpenId());
        }
        if (Objects.nonNull(userModel.getUserId())) {
            userService.update(userModel);
        }

        if (StringUtils.isNoneBlank(wechatLoginDto.getOpenId())) {
            userService.saveUserLoginWx(inModel.getUserId(), request.getLoginEnum().getAccountType(), request.getCompanyKey(), wechatLoginDto.getOpenId());
        }
    }

    private void saveUser(Integer companyId, WxUserDetail userDetail) {
        User inModel = new User();
        inModel.setUnionid(userDetail.getWechatLoginDto().getUnionId());
        inModel.setEnterpriseId(companyId);
        if (Objects.nonNull(userDetail.getUserInfoDto())) {
            inModel.setNickeName(userDetail.getUserInfoDto().getNickName());
            inModel.setAvatarUrl(userDetail.getUserInfoDto().getAvatarUrl());
            inModel.setGender(userDetail.getUserInfoDto().getGender());
            inModel.setCity(userDetail.getUserInfoDto().getCity());
            inModel.setProvince(userDetail.getUserInfoDto().getProvince());
            inModel.setCountry(userDetail.getUserInfoDto().getCountry());
        }
        inModel.setOpenId(userDetail.getWechatLoginDto().getOpenId());
        userService.saveUser(inModel);

        userDetail.setUserModel(inModel);
    }

    private void codeOauth(WxCodeRequestDetail request, ClientDetail clientDetail, WxUserDetail userDetail, boolean isOneUserLogin) {
        AccountResponse companyAccountModel = clientDetail.getCompanyAccountModel();
        WechatLoginDto wechatLoginDto = wxLoginService.code2accessToken(request.getCode(), companyAccountModel.getAppId(), companyAccountModel.getAppSecret());
        WechatUserInfoDto userInfoDto = null;
        if (StringUtils.isNoneBlank(request.getEncrypteData())) {
            userInfoDto = wxLoginService.getUserInfo(request.getEncrypteData(), wechatLoginDto.getSessionKey(), request.getIv());
        }
        if (StringUtils.isNoneBlank(wechatLoginDto.getUnionId()) && Objects.nonNull(userInfoDto)) {
            wechatLoginDto.setUnionId(userInfoDto.getUnionid());
        }

        User inModel = userService.getByWx(wechatLoginDto.getUnionId(), request.getLoginEnum(), request.getCompanyKey(), wechatLoginDto.getOpenId());

        userDetail.setWechatLoginDto(wechatLoginDto);
        userDetail.setUserInfoDto(userInfoDto);
        userDetail.setUserModel(inModel);
    }

    private boolean isOneUserLogin(String companyKey) {
        CompanyPlatform companyPlatform = companyPlatformMapperServiceLoginExt.select(companyKey);
        return companyPlatform != null && companyPlatform.getType() == PlatformApi.TYPE_ALONE;
    }

    @Data
    @EqualsAndHashCode(callSuper = true)
    public static class WxUserDetail extends UserDetail {
        private WechatLoginDto wechatLoginDto;
        private WechatUserInfoDto userInfoDto;
    }
}
